<?php

declare(strict_types=1);

namespace App\Common\Modular\Administer\Serve;

use App\Common\GuardModel\AdminGuard;
use App\Common\Modular\Administer\Enums\UserEnums;
use App\Common\Modular\Administer\Model\UserModel;
use Core\Basics\BasicsModel;
use Core\Basics\BasicsServe;
use Zms\Exception\AppException;
use Zms\PasswordVerifier\PasswordVerifier;

class UserServe extends BasicsServe
{

    /**
     * @return UserModel::class
     */
    public static function model(): string
    {
        return UserModel::class;
    }


    /**
     * 是否是根账号
     * @param int $id
     * @return bool
     */
    public function isRootUser(int $id): bool
    {
        return $id === 1;
    }


    /**
     * 检查账号状态
     * @param int|UserModel $user
     * @return bool|string
     */
    public function checkAccountStatus(int|UserModel $user): bool|string
    {
        if (!($user instanceof UserModel)) {
            $user = $this->search(['id' => $user])->first();
        }
        if (!$user) return '账号已失效';
        if ($user->status === UserEnums::STATUS_STOP) {
            return '此账号已禁用';
        }
        if ($user->locking > time()) {
            return '此账号当前已被锁定';
        }
        return true;
    }


    /**
     * @param array $values
     * @return BasicsModel|false
     * @throws AppException
     */
    public function created(array $values): BasicsModel|false
    {
        if (isset($values['account'])) {
            if ($this->search(['account' => $values['account']])->exists()) {
                throw new AppException("账号'{$values['account']}'已被使用,请更换账号");
            }
        }
        $guard = (new AdminGuard);
        $values['secret_key'] = $guard->generateSecretKey();
        if (isset($values['password'])) {
            $error = $this->checkPassword($values['password']);
            if ($error !== true) {
                throw new AppException($error);
            }
            $values['password'] = $guard->generatePassword($values['password'], $values['secret_key']);
        }
        return parent::created($values);
    }


    /**
     * 更新数据
     * @param array $data
     * @param array|null|string $where
     * @param bool $returnModel
     * @return bool|BasicsModel
     * @throws AppException
     */
    public function updated(array $data, null|array|string $where = null, bool $returnModel = false): bool|BasicsModel
    {
        if (isset($data['account']) && isset($data['id'])) {
            if ($this->search(['account' => $data['account']])->whereRaw("`id` != ?", [$data['id']])->exists()) {
                throw new AppException("账号'{$data['account']}'已被使用,请更换账号");
            }
        }
        if (isset($data['password'])) {
            if (strlen($data['password']) > 0) {
                $data['secret_key'] = (new AdminGuard)->generateSecretKey();
                $error = $this->checkPassword($data['password']);
                if ($error !== true) {
                    throw new AppException($error);
                }
                $data['password'] = (new AdminGuard)->generatePassword($data['password'], $data['secret_key']);
            } else {
                unset($data['secret_key']);
                unset($data['password']);
            }
        }
        return parent::updated($data, $where, $returnModel);
    }


    /**
     * 密码规则检测
     * @param string $password
     * @return bool|string
     */
    public function checkPassword(string $password): bool|string
    {
        $min_length = intval(configure('admimpwd.min_length', 5) ?: 5);
        $max_length = intval(configure('admimpwd.max_length', 30) ?: 30);
        $element = configure('admimpwd.element');
        $verifier = new PasswordVerifier(['min_length' => $min_length, 'max_length' => $max_length, 'element' => is_array($element) ? $element : []]);
        if ($verifier->verifier($password) === false) {
            return $verifier->getError();
        }
        return true;
    }
}